paint-brush
रिएक्ट, सॉलिडिटी और कॉमेटचैट के साथ एक लाभदायक एनएफटी मार्केटप्लेस कैसे बनाएंद्वारा@daltonic
13,916 रीडिंग
13,916 रीडिंग

रिएक्ट, सॉलिडिटी और कॉमेटचैट के साथ एक लाभदायक एनएफटी मार्केटप्लेस कैसे बनाएं

द्वारा Darlington Gospel 74m2022/07/23
Read on Terminal Reader
Read this story w/o Javascript

बहुत लंबा; पढ़ने के लिए

यह ट्यूटोरियल आपको सिखाएगा कि चैट कार्यक्षमता के साथ एक लाभदायक और अच्छी तरह से डिज़ाइन किया गया NFT बाज़ार कैसे बनाया जाए। यह अपूरणीय टोकन (एनएफटी) बनाने और स्वामित्व अधिकारों को बनाए रखते हुए परिसंपत्तियों को डिजिटल बनाने के लिए वेब3 तकनीक का उपयोग करेगा। इस बिल्ड को सफलतापूर्वक कुचलने के लिए आपको निम्नलिखित टूल की आवश्यकता होगी: नोड, गनाचे-क्ली और ट्रफल।

Companies Mentioned

Mention Thumbnail
Mention Thumbnail

Coin Mentioned

Mention Thumbnail
featured image - रिएक्ट, सॉलिडिटी और कॉमेटचैट के साथ एक लाभदायक एनएफटी मार्केटप्लेस कैसे बनाएं
Darlington Gospel  HackerNoon profile picture


आप क्या बना रहे हैं, रिंकीबी टेस्ट नेटवर्क पर एक डेमो देखें और यहां गिट रेपो ...


परिचय

Web3 इंटरनेट का भविष्य है, और हम सभी को इस तकनीक को सीखना और अपनाना चाहिए। इसके उपयोग के मामले सामने आते रहते हैं और इसका दुनिया पर सकारात्मक प्रभाव पड़ता है।


वेब3 तकनीक का एक शानदार अनुप्रयोग अपूरणीय टोकन (एनएफटी) का निर्माण है, जो स्वामित्व अधिकारों को बनाए रखते हुए परिसंपत्तियों को डिजिटल बनाने के लिए एक व्यवहार्य समाधान है।



यह ट्यूटोरियल आपको सिखाएगा कि चैट कार्यक्षमता के साथ एक लाभदायक और अच्छी तरह से डिज़ाइन किया गया NFT बाज़ार कैसे बनाया जाए।


यदि आपको किसी ऐसे व्यक्ति की आवश्यकता है जो वेब3 के विकास को तेज़ी से सीखने में आपकी सहायता करे, तो मेरे साथ अपनी निजी कक्षाएं बुक करें


इसके साथ ही, चलिए शुरू करते हैं ...


अब मुफ़्त वेब3 ट्यूटोरियल के लिए मेरा यूट्यूब चैनल देखें .

शर्त

इस बिल्ड को सफलतापूर्वक कुचलने के लिए आपको निम्नलिखित टूल इंस्टॉल करने होंगे:

  • नोड
  • गनाचे-क्ली
  • कवक
  • प्रतिक्रिया
  • इंफुरा
  • टेलविंड सीएसएस
  • कॉमेटचैट एसडीके
  • मेटामास्क
  • धागा

निर्भरता स्थापित करना

NodeJs इंस्टालेशन जांचें कि NodeJs पहले से ही आपकी मशीन पर स्थापित है, और यदि नहीं, तो इसे HERE से इंस्टॉल करें। यह सुनिश्चित करने के लिए टर्मिनल पर कोड फिर से चलाएँ कि यह स्थापित है।


यार्न, गनाचे-क्ली और ट्रफल इंस्टॉलेशन इन महत्वपूर्ण पैकेजों को विश्व स्तर पर स्थापित करने के लिए अपने टर्मिनल में नीचे दिए गए कमांड चलाएँ।


 npm i -g yarn npm i -g truffle npm i -g ganache-cli


स्थापना की पुष्टि करने के लिए, टर्मिनल में निम्न कोड दर्ज करें।


 yarn --version && ganache-cli --version && truffle version 

वेब3 स्टार्टर प्रोजेक्ट की क्लोनिंग नीचे दिए गए कमांड का उपयोग करके वेब 3.0 स्टार्टर प्रोजेक्ट को क्लोन करें। यह सुनिश्चित करता है कि हम सभी एक ही पृष्ठ पर हैं और एक ही सॉफ़्टवेयर का उपयोग कर रहे हैं।


 git clone https://github.com/Daltonic/timelessNFT


बढ़िया, कृपया **package.json** फ़ाइल को निम्न से बदलें:


 { "name": "TimelessNFT", "private": true, "version": "0.0.0", "scripts": { "start": "react-app-rewired start", "build": "react-app-rewired build", "test": "react-app-rewired test", "eject": "react-scripts eject" }, "dependencies": { "@cometchat-pro/chat": "^3.0.9", "ipfs-http-client": "^56.0.0", "moment": "^2.29.4", "moment-timezone": "^0.5.34", "react": "^17.0.2", "react-dom": "^17.0.2", "react-hooks-global-state": "^1.0.2", "react-icons": "^4.3.1", "react-identicons": "^1.2.5", "react-moment": "^1.1.2", "react-router-dom": "6", "react-scripts": "5.0.0", "web-vitals": "^2.1.4", "web3": "^1.7.1" }, "devDependencies": { "@faker-js/faker": "^6.0.0-alpha.5", "@openzeppelin/contracts": "^4.5.0", "@tailwindcss/forms": "0.4.0", "@truffle/hdwallet-provider": "^2.0.4", "assert": "^2.0.0", "autoprefixer": "10.4.2", "babel-polyfill": "^6.26.0", "babel-preset-env": "^1.7.0", "babel-preset-es2015": "^6.24.1", "babel-preset-stage-2": "^6.24.1", "babel-preset-stage-3": "^6.24.1", "babel-register": "^6.26.0", "buffer": "^6.0.3", "chai": "^4.3.6", "chai-as-promised": "^7.1.1", "crypto-browserify": "^3.12.0", "dotenv": "^16.0.0", "https-browserify": "^1.0.0", "mnemonics": "^1.1.3", "os-browserify": "^0.3.0", "postcss": "8.4.5", "process": "^0.11.10", "react-app-rewired": "^2.1.11", "sharp": "^0.30.1", "stream-browserify": "^3.0.0", "stream-http": "^3.2.0", "tailwindcss": "3.0.18", "url": "^0.11.0" }, "browserslist": { "production": [ ">0.2%", "not dead", "not op_mini all" ], "development": [ "last 1 chrome version", "last 1 firefox version", "last 1 safari version" ] } }


निर्देशानुसार संकुल को बदलने के बाद, निर्दिष्ट संस्करणों के साथ सभी संकुल लोड करने के लिए अपने टर्मिनल पर **yarn install** चलाएं।

कॉमेटचैट एसडीके को कॉन्फ़िगर करना

कॉमेटचैट एसडीके को कॉन्फ़िगर करने के लिए नीचे दिए गए चरणों का पालन करें; अंत में, आपको इन कुंजियों को एक पर्यावरण चर के रूप में सहेजना होगा।


चरण 1: कॉमेटचैट डैशबोर्ड पर जाएं और एक खाता बनाएं।


चरण 2: कॉमेटचैट डैशबोर्ड में पंजीकरण के बाद ही लॉग इन करें।


चरण 3: डैशबोर्ड से, टाइमलेसएनएफटी नामक एक नया ऐप जोड़ें


चरण 4: सूची से आपके द्वारा अभी बनाया गया ऐप चुनें।


चरण 5: त्वरित प्रारंभ से APP_ID , REGION , और AUTH_KEY को अपनी .env फ़ाइल में कॉपी करें। छवि और कोड स्निपेट देखें।


REACT_COMET_CHAT प्लेसहोल्डर कुंजियों को उनके उपयुक्त मानों से बदलें।

 REACT_APP_COMET_CHAT_REGION=** REACT_APP_COMET_CHAT_APP_ID=************** REACT_APP_COMET_CHAT_AUTH_KEY=******************************

इंफुरा ऐप को कॉन्फ़िगर करना

चरण 1: इंफुरा पर जाएं, और एक खाता बनाएं।



चरण 2: डैशबोर्ड से एक नया प्रोजेक्ट बनाएं।



चरण 3: अपनी .env फ़ाइल में Rinkeby परीक्षण नेटवर्क WebSocket समापन बिंदु URL की प्रतिलिपि बनाएँ।



उसके बाद, अपना मेटामास्क गुप्त वाक्यांश और पसंदीदा खाते की निजी कुंजी दर्ज करें। यदि आपने निर्देशों का सही ढंग से पालन किया है, तो आपके पर्यावरण चर अब इस तरह दिखने चाहिए।


 ENDPOINT_URL=*************************** DEPLOYER_KEY=********************** REACT_APP_COMET_CHAT_REGION=** REACT_APP_COMET_CHAT_APP_ID=************** REACT_APP_COMET_CHAT_AUTH_KEY=******************************


यदि आप नहीं जानते कि अपनी निजी कुंजी का उपयोग कैसे करें, तो नीचे दिया गया अनुभाग देखें।

अपने मेटामास्क निजी कुंजी तक पहुंचना

चरण 1: सुनिश्चित करें कि आपके मेटामास्क ब्राउज़र एक्सटेंशन में रिंकीबी को परीक्षण नेटवर्क के रूप में चुना गया है। फिर, पसंदीदा खाते पर, लंबवत बिंदीदार रेखा पर क्लिक करें और खाता विवरण चुनें। कृपया नीचे दी गई छवि देखें।


चरण 2: दिए गए क्षेत्र में अपना पासवर्ड दर्ज करें और पुष्टि बटन पर क्लिक करें, इससे आप अपने खाते की निजी कुंजी तक पहुंच सकेंगे।


चरण 3: अपनी निजी कुंजी देखने के लिए "निजी कुंजी निर्यात करें" पर क्लिक करें। सुनिश्चित करें कि आप अपनी चाबियों को कभी भी सार्वजनिक पृष्ठ जैसे कि Github पर उजागर न करें। इसलिए हम इसे एक पर्यावरण चर के रूप में जोड़ रहे हैं।


चरण 4: अपनी निजी कुंजी को अपनी .env फ़ाइल में कॉपी करें। नीचे दी गई छवि और कोड स्निपेट देखें।



 ENDPOINT_URL=*************************** SECRET_KEY=****************** DEPLOYER_KEY=********************** REACT_APP_COMET_CHAT_REGION=** REACT_APP_COMET_CHAT_APP_ID=************** REACT_APP_COMET_CHAT_AUTH_KEY=******************************


जहां तक आपके SECRET_KEY का संबंध है, आपको अपने Metamask गुप्त वाक्यांश को पर्यावरण फ़ाइल में दिए गए स्थान में चिपकाना होगा।

कालातीत एनएफटी स्मार्ट अनुबंध

यहाँ संपूर्ण स्मार्ट अनुबंध कोड है; आइए एक-एक करके सभी फंक्शन और वेरिएबल पर चलते हैं।


 // SPDX-License-Identifier: MIT pragma solidity >=0.7.0 <0.9.0; import "./ERC721.sol"; import "./ERC721Enumerable.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; contract TimelessNFT is ERC721Enumerable, Ownable { using Strings for uint256; mapping(string => uint8) existingURIs; mapping(uint256 => address) public holderOf; address public artist; uint256 public royalityFee; uint256 public supply = 0; uint256 public totalTx = 0; uint256 public cost = 0.01 ether; event Sale( uint256 id, address indexed owner, uint256 cost, string metadataURI, uint256 timestamp ); struct TransactionStruct { uint256 id; address owner; uint256 cost; string title; string description; string metadataURI; uint256 timestamp; } TransactionStruct[] transactions; TransactionStruct[] minted; constructor( string memory _name, string memory _symbol, uint256 _royalityFee, address _artist ) ERC721(_name, _symbol) { royalityFee = _royalityFee; artist = _artist; } function payToMint( string memory title, string memory description, string memory metadataURI, uint256 salesPrice ) external payable { require(msg.value >= cost, "Ether too low for minting!"); require(existingURIs[metadataURI] == 0, "This NFT is already minted!"); require(msg.sender != owner(), "Sales not allowed!"); uint256 royality = (msg.value * royalityFee) / 100; payTo(artist, royality); payTo(owner(), (msg.value - royality)); supply++; minted.push( TransactionStruct( supply, msg.sender, salesPrice, title, description, metadataURI, block.timestamp ) ); emit Sale( supply, msg.sender, msg.value, metadataURI, block.timestamp ); _safeMint(msg.sender, supply); existingURIs[metadataURI] = 1; holderOf[supply] = msg.sender; } function payToBuy(uint256 id) external payable { require(msg.value >= minted[id - 1].cost, "Ether too low for purchase!"); require(msg.sender != minted[id - 1].owner, "Operation Not Allowed!"); uint256 royality = (msg.value * royalityFee) / 100; payTo(artist, royality); payTo(minted[id - 1].owner, (msg.value - royality)); totalTx++; transactions.push( TransactionStruct( totalTx, msg.sender, msg.value, minted[id - 1].title, minted[id - 1].description, minted[id - 1].metadataURI, block.timestamp ) ); emit Sale( totalTx, msg.sender, msg.value, minted[id - 1].metadataURI, block.timestamp ); minted[id - 1].owner = msg.sender; } function changePrice(uint256 id, uint256 newPrice) external returns (bool) { require(newPrice > 0 ether, "Ether too low!"); require(msg.sender == minted[id - 1].owner, "Operation Not Allowed!"); minted[id - 1].cost = newPrice; return true; } function payTo(address to, uint256 amount) internal { (bool success, ) = payable(to).call{value: amount}(""); require(success); } function getAllNFTs() external view returns (TransactionStruct[] memory) { return minted; } function getNFT(uint256 id) external view returns (TransactionStruct memory) { return minted[id - 1]; } function getAllTransactions() external view returns (TransactionStruct[] memory) { return transactions; } }


कोड आयात और अनुबंध की जानकारी नीचे दिए गए कोड में, हमने लाइसेंस पहचानकर्ता के सॉलिडिटी कंपाइलर और इस कोड को संकलित करने के लिए योग्य कंपाइलर संस्करणों को सूचित किया।


 // SPDX-License-Identifier: MIT pragma solidity >=0.7.0 <0.9.0; import "./ERC721.sol"; import "./ERC721Enumerable.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; contract TimelessNFT is ERC721Enumerable, Ownable { // codes goes in here... }


साथ ही, यह स्मार्ट अनुबंध कुछ openzepplin's ERC721 स्मार्ट अनुबंधों का उपयोग करता है। आपको यह सुनिश्चित करना होगा कि आपने उन्हें उसी निर्देशिका में रखा है जैसा कि नीचे दी गई छवि में देखा गया है।


इस लिंक पर जाएं और इन स्मार्ट अनुबंधों को डाउनलोड करें जैसा कि ऊपर की छवि में दिखाया गया है।


राज्य चर घोषणाएं

 using Strings for uint256; mapping(string => uint8) existingURIs; mapping(uint256 => address) public holderOf; address public artist; uint256 public royalityFee; uint256 public supply = 0; uint256 public totalTx = 0; uint256 public cost = 0.01 ether;


हमने निर्दिष्ट किया है कि हम स्ट्रिंग लायब्रेरी का उपयोग uint से string संचालन करने के लिए कर रहे हैं। इसके बाद, हमने खनन किए गए एनएफटी कलाकृतियों को रिकॉर्ड करने और टोकन के वर्तमान मालिक को जानने के लिए भी मैपिंग की घोषणा की।


फिर हमने कलाकार खाते, रॉयल्टी शुल्क, वर्तमान आपूर्ति, प्लेटफॉर्म पर किए गए कुल लेनदेन और एनएफटी की टकसाल लागत को कैप्चर करने के लिए अन्य आवश्यक चर निर्दिष्ट किए।


घटनाओं और संरचनाओं की स्थापना

 event Sale( uint256 id, address indexed owner, uint256 cost, string metadataURI, uint256 timestamp ); struct TransactionStruct { uint256 id; address owner; uint256 cost; string title; string description; string metadataURI; uint256 timestamp; } TransactionStruct[] transactions; TransactionStruct[] minted;


पिछले कोड में, हमारे पास एक बिक्री घटना है जो स्मार्ट अनुबंध पर होने वाले किसी भी लेनदेन से डेटा उत्सर्जित करती है, चाहे वह खनन या एनएफटी हस्तांतरण पर हो।


हमने खनन या स्थानांतरित एनएफटी के बारे में डेटा एकत्र करने के लिए एक लेनदेन संरचना तैयार की है। हमारे द्वारा परिभाषित लेन-देन संरचना का उपयोग करते हुए, हमने transactions नामक दो चर बनाए और minted


कंस्ट्रक्टर को इनिशियलाइज़ करना

 constructor( string memory _name, string memory _symbol, uint256 _royalityFee, address _artist ) ERC721(_name, _symbol) { royalityFee = _royalityFee; artist = _artist; }


स्मार्ट कॉन्ट्रैक्ट को इनिशियलाइज़ करने के लिए कंस्ट्रक्टर चार पैरामीटर लेता है। एक टोकन नाम, प्रतीक, एक कलाकार खाता, और प्रति लेनदेन एक रॉयल्टी शुल्क। टोकन नाम और प्रतीक को तैनाती के दौरान ERC721 स्मार्ट अनुबंध में पारित किया जाता है।


मिंट फंक्शन एल्गोरिथम

 function payToMint( string memory title, string memory description, string memory metadataURI, uint256 salesPrice ) external payable { require(msg.value >= cost, "Ether too low for minting!"); require(existingURIs[metadataURI] == 0, "This NFT is already minted!"); require(msg.sender != owner(), "Sales not allowed!"); uint256 royality = (msg.value * royalityFee) / 100; payTo(artist, royality); payTo(owner(), (msg.value - royality)); supply++; minted.push( TransactionStruct( supply, msg.sender, salesPrice, title, description, metadataURI, block.timestamp ) ); emit Sale( supply, msg.sender, msg.value, metadataURI, block.timestamp ); _safeMint(msg.sender, supply); existingURIs[metadataURI] = 1; holderOf[supply] = msg.sender; }


उपरोक्त फ़ंक्शन स्मार्ट अनुबंध पर नए टोकन बनाने के लिए जिम्मेदार है। इस पद्धति के कॉलर को चार पैरामीटर प्रदान करने होंगे जिनमें शामिल हैं; एक NFT शीर्षक, विवरण, मेटाडेटा URI, और ढालने के बाद NFT का विक्रय मूल्य।


यह सुनिश्चित करने के लिए सत्यापन किया जाता है कि एनएफटी खनन कर रहा है और प्रत्येक खनन के लिए किए गए भुगतान के अनुसार किया जाता है। साथ ही, सत्यापन यह सुनिश्चित करता है कि प्रत्येक कलाकृति विशिष्ट रूप से एक टोकन के साथ जुड़ी हुई है, और किसी अन्य टोकन में समान कलाकृति नहीं है। अंत में सत्यापन के लिए, हमने सुनिश्चित किया कि इस पद्धति का कॉलर स्मार्ट अनुबंध का नियोक्ता नहीं है, यह सुनिश्चित करने के लिए है कि हम चीजों को बहुत खराब न करें।


फ़ंक्शन में अगला भुगतान साझाकरण नियम है। रॉयल्टी प्रतिशत कलाकार के पास जाता है और बाकी ईथर मालिक के पास जाता है।


बाद में, हमने उस एनएफटी को मिनेटेड एरे के अंदर रिकॉर्ड किया और एक बिक्री कार्यक्रम का उत्सर्जन किया। अंत में, हमने कॉलर के पते को टोकन के मालिक के रूप में रिकॉर्ड करते हुए एनएफटी का खनन किया।


एनएफटी ट्रांसफर फंक्शन एल्गोरिथम

 function payToBuy(uint256 id) external payable { require(msg.value >= minted[id - 1].cost, "Ether too low for purchase!"); require(msg.sender != minted[id - 1].owner, "Operation Not Allowed!"); uint256 royality = (msg.value * royalityFee) / 100; payTo(artist, royality); payTo(minted[id - 1].owner, (msg.value - royality)); totalTx++; transactions.push( TransactionStruct( totalTx, msg.sender, msg.value, minted[id - 1].title, minted[id - 1].description, minted[id - 1].metadataURI, block.timestamp ) ); emit Sale( totalTx, msg.sender, msg.value, minted[id - 1].metadataURI, block.timestamp ); minted[id - 1].owner = msg.sender; }


उपरोक्त फ़ंक्शन NFT आईडी लेता है और minter (मालिक) द्वारा निर्धारित मूल्य के अनुसार NFT की खरीदारी करता है।


मालिकों को अपने एनएफटी और अन्य को शून्य ईथर के साथ खरीदने से रोकने के लिए आवश्यक सत्यापन किए जाते हैं।


इसके बाद, कलाकार के खाते में एक रॉयल्टी शुल्क भेजा जाता है और NFT के वर्तमान मालिक को शेष राशि रखनी होती है।


प्लेटफ़ॉर्म पर किए गए सभी लेन-देन का ट्रैक रखने के लिए प्रत्येक टोकन हस्तांतरण को लेनदेन सरणी में दर्ज किया जाता है।


बाद में, ईवीएम पर लॉग किए गए डेटा को समृद्ध करने के लिए इस खरीद के लिए एक बिक्री घटना फिर से उत्सर्जित की जाती है।


अन्य आवश्यक कार्य

 // changes the price of an NFT function changePrice(uint256 id, uint256 newPrice) external returns (bool) { require(newPrice > 0 ether, "Ether too low!"); require(msg.sender == minted[id - 1].owner, "Operation Not Allowed!"); minted[id - 1].cost = newPrice; return true; } // sends ethers to a specific account function payTo(address to, uint256 amount) internal { (bool success, ) = payable(to).call{value: amount}(""); require(success); } // returns all minted NFTs function getAllNFTs() external view returns (TransactionStruct[] memory) { return minted; } // returns a specific NFT by token id function getNFT(uint256 id) external view returns (TransactionStruct memory) { return minted[id - 1]; } // returns all transactions function getAllTransactions() external view returns (TransactionStruct[] memory) { return transactions; }


और वहां आपके पास स्मार्ट अनुबंध विकसित करने के लिए है, हम अगली बार ReactJs के साथ UI घटकों के निर्माण में गोता लगाएंगे।

परिनियोजन स्क्रिप्ट को कॉन्फ़िगर करना

स्मार्ट अनुबंध के साथ एक और बात परिनियोजन स्क्रिप्ट को कॉन्फ़िगर करना है।

प्रोजेक्ट हेड पर माइग्रेशन फोल्डर >> 2_deploy_contracts.js पर जाएं और इसे नीचे दिए गए कोड स्निपेट से अपडेट करें।


 const TimelessNFT = artifacts.require('TimelessNFT') module.exports = async (deployer) => { const accounts = await web3.eth.getAccounts() await deployer.deploy( TimelessNFT, 'Timeless NFTs', 'TNT', 10, accounts[1] ) }


शानदार, हमने अभी-अभी अपने आवेदन के लिए स्मार्ट अनुबंध समाप्त किया है; अब डीएपी इंटरफेस पर आरंभ करने का समय आ गया है। यदि आपको स्मार्ट अनुबंध विकास सीखने में मदद करने के लिए एक निजी ट्यूटर की आवश्यकता है, तो मेरे साथ अपनी कक्षाएं बुक करें

फ्रंटएंड का विकास

सामने का छोर कई घटकों और भागों से बना है। सभी घटकों, विचारों और बाह्य उपकरणों को हमारे द्वारा बनाया जाएगा।


हैडर घटक


यह घटक टेलविंड सीएसएस के साथ बनाया गया था और मेटामास्क वॉलेट तक पहुंचने के लिए गुलाबी Connect Wallet बटन का उपयोग करता है। नीचे दिए गए कोड प्रोग्रामिंग को प्रदर्शित करते हैं।


 import { useGlobalState } from '../store' import timelessLogo from '../assets/timeless.png' import { connectWallet } from '../TimelessNFT' const Header = () => { const [connectedAccount] = useGlobalState('connectedAccount') return ( <nav className="w-4/5 flex md:justify-center justify-between items-center py-4 mx-auto"> <div className="md:flex-[0.5] flex-initial justify-center items-center"> <img className="w-32 cursor-pointer" src={timelessLogo} alt="Timeless Logo" /> </div> <ul className="md:flex-[0.5] text-white md:flex hidden list-none flex-row justify-between items-center flex-initial" > <li className="mx-4 cursor-pointer">Market</li> <li className="mx-4 cursor-pointer">Artist</li> <li className="mx-4 cursor-pointer">Features</li> <li className="mx-4 cursor-pointer">Community</li> </ul> {!connectedAccount ? ( <button className="shadow-xl shadow-black text-white bg-[#e32970] hover:bg-[#bd255f] md:text-xs p-2 rounded-full cursor-pointer" onClick={connectWallet} > Connect Wallet </button> ) : ( <></> )} </nav> ) } export default Header


हीरो घटक


यह घटक कनेक्टेड वॉलेट को प्रदर्शित करने और एक नया एनएफटी बनाने के लिए उपयोग किए जाने वाले मोडल को लॉन्च करने के लिए भी जिम्मेदार है। इसके अतिरिक्त, यह एनएफटी के विक्रेता के साथ आमने-सामने चैट के लिए उपयोगकर्ताओं को साइन इन या अप करने के लिए जिम्मेदार है। इन कार्यों के लिए जिम्मेदार कोड यहां दिया गया है।


 import Identicon from 'react-identicons' import { setGlobalState, useGlobalState, truncate } from '../store' import { getConversations, loginWithCometChat, signUpWithCometChat } from '../CometChat' import ChatList from './ChatList' import { useState } from 'react' const Hero = () => { const [connectedAccount] = useGlobalState('connectedAccount') const [currentUser] = useGlobalState('currentUser') const [recentOpened] = useGlobalState('recentOpened') const [conversations, setConversations] = useState([]) const onCreatedNFT = () => { if (currentUser?.uid.toLowerCase() != connectedAccount.toLowerCase()) return alert('Please login to receive chats from buyers!') setGlobalState('modal', 'scale-100') } const onLunchRecent = () => { getConversations().then((convs) => { setConversations(convs) setGlobalState('recentOpened', true) }) } return ( <div className="flex flex-col md:flex-row w-4/5 justify-between items-center mx-auto py-10" > <div className="md:w-3/6 w-full"> <div> <h1 className="text-white text-5xl font-bold"> Buy and Sell <br /> Digital Arts, <br /> <span className="text-gradient">NFTs</span> Collections </h1> <p className="text-gray-500 font-semibold text-sm mt-3"> Mint and collect the hottest NFTs around. </p> </div> <div className="flex flex-row mt-5"> {connectedAccount ? ( <> <button className="shadow-xl shadow-black text-white bg-[#e32970] hover:bg-[#bd255f] rounded-full cursor-pointer p-2" onClick={onCreatedNFT} > Create NFT </button> <> {currentUser?.uid.toLowerCase() == connectedAccount.toLowerCase() ? ( <button className="text-white border border-gray-500 hover:border-[#e32970] hover:bg-[#bd255f] cursor-pointer rounded-full p-2 mx-3" onClick={onLunchRecent} > Recent Chats </button> ) : ( <> <button className="text-white border border-gray-500 hover:border-[#e32970] hover:bg-[#bd255f] cursor-pointer rounded-full p-2 mx-3" onClick={() => loginWithCometChat(connectedAccount)} > Login for Chat </button> <button className="text-white border border-gray-500 hover:border-[#e32970] hover:bg-[#bd255f] cursor-pointer rounded-full p-2 mx-3" onClick={() => signUpWithCometChat(connectedAccount, connectedAccount)} > Signup for Chat </button> </> )} </> </> ) : null} </div> <div className="w-3/4 flex justify-between items-center mt-5"> <div> <p className="text-white font-bold">1231k</p> <small className="text-gray-300">User</small> </div> <div> <p className="text-white font-bold">152k</p> <small className="text-gray-300">Artwork</small> </div> <div> <p className="text-white font-bold">200k</p> <small className="text-gray-300">Artist</small> </div> </div> </div> <div className="shadow-xl shadow-black md:w-2/5 w-full mt-10 md:mt-0 rounded-md overflow-hidden bg-gray-800" > <img src="https://images.cointelegraph.com/images/1434_aHR0cHM6Ly9zMy5jb2ludGVsZWdyYXBoLmNvbS91cGxvYWRzLzIwMjEtMDYvNGE4NmNmOWQtODM2Mi00YmVhLThiMzctZDEyODAxNjUxZTE1LmpwZWc=.jpg" alt="NFT Art" className="h-60 w-full object-cover" /> <div className="flex justify-start items-center p-3"> <Identicon string={ connectedAccount ? connectedAccount.toLowerCase() : 'Connect Your Wallet' } size={50} className="h-10 w-10 object-contain rounded-full mr-3" /> <div> <p className="text-white font-semibold"> {connectedAccount ? truncate(connectedAccount, 4, 4, 11) : 'Connect Your Wallet'} </p> <small className="text-pink-800 font-bold">@you</small> </div> </div> </div> {recentOpened ? <ChatList users={conversations} /> : null} </div> ) } export default Hero


कलाकृति घटक

यह घटक खूबसूरती से तैयार किए गए टेलविंड सीएसएस कार्ड का उपयोग करके प्लेटफॉर्म पर ढाले गए एनएफटी की सूची को प्रस्तुत करने के लिए जिम्मेदार है। प्रत्येक कार्ड में एक NFT छवि, शीर्षक, विवरण, मूल्य और स्वामी होता है। इसके कार्यान्वयन के लिए नीचे दिए गए कोड देखें।


 import { useEffect, useState } from 'react' import { setGlobalState, useGlobalState, truncate } from '../store' const Artworks = () => { const [nfts] = useGlobalState('nfts') const [end, setEnd] = useState(4) const [count] = useState(4) const [collection, setCollection] = useState([]) const setNFT = (nft) => { setGlobalState('nft', nft) setGlobalState('showModal', 'scale-100') } const getCollection = () => { return nfts.slice(0, end) } useEffect(() => { setCollection(getCollection()) }, [nfts, end]) return ( <div className="bg-[#151c25] gradient-bg-artworks"> <div className="w-4/5 py-10 mx-auto"> <h4 className="text-white text-3xl font-bold uppercase text-gradient"> {collection.length > 0 ? 'Latest Artworks' : 'No Artworks Yet'} </h4> <div className="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-4 gap-6 md:gap-4 lg:gap-3 py-2.5"> {collection.map((nft) => ( <div key={nft.id} className="w-full shadow-xl shadow-black rounded-md overflow-hidden bg-gray-800 my-2 p-3" > <img src={nft.metadataURI} alt={truncate(nft.title, 6)} className="h-60 w-full object-cover shadow-lg shadow-black rounded-lg mb-3" /> <h4 className="text-white font-semibold">{nft.title}</h4> <p className="text-gray-400 text-xs my-1"> {truncate(nft.description)} </p> <div className="flex justify-between items-center mt-3 text-white"> <div className="flex flex-col"> <small className="text-xs">Current Price</small> <p className="text-sm font-semibold">{nft.cost} ETH</p> </div> <button onClick={() => setNFT(nft)} className="shadow-lg shadow-black text-white text-sm bg-[#e32970] hover:bg-[#bd255f] cursor-pointer rounded-full px-1.5 py-1" > View Details </button> </div> </div> ))} </div> {collection.length > 0 && nfts.length > collection.length ? ( <div className="text-center my-5"> <button className="shadow-xl shadow-black text-white bg-[#e32970] hover:bg-[#bd255f] rounded-full cursor-pointer p-2" onClick={() => setEnd(end + count)} > Load More </button> </div> ) : null} </div> </div> ) } export default Artworks


लेनदेन घटक

यह घटक हमारे स्मार्ट अनुबंध में हुए सभी लेनदेन को प्रस्तुत करने के लिए जिम्मेदार है। उदाहरण के लिए एक लेन-देन होगा एलिसन ड्यूक से एक एनएफटी खरीद रहा है। इस खरीद को इस घटक में लेन-देन के रूप में कैप्चर किया जाएगा। नीचे स्निपेट देखें।


 import { useEffect, useState } from 'react' import { BiTransfer } from 'react-icons/bi' import { MdOpenInNew } from 'react-icons/md' import { useGlobalState, truncate } from '../store' const Transactions = () => { const [transactions] = useGlobalState('transactions') const [end, setEnd] = useState(3) const [count] = useState(3) const [collection, setCollection] = useState([]) const getCollection = () => { return transactions.slice(0, end) } useEffect(() => { setCollection(getCollection()) }, [transactions, end]) return ( <div className="bg-[#151c25]"> <div className="w-4/5 py-10 mx-auto"> <h4 className="text-white text-3xl font-bold uppercase text-gradient"> {collection.length > 0 ? 'Latest Transactions' : 'No Transaction Yet'} </h4> <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 md:gap-4 lg:gap-2 py-2.5"> {collection .map((tx) => ( <div key={tx.id} className="flex justify-between items-center border border-pink-500 text-gray-400 w-full shadow-xl shadow-black rounded-md overflow-hidden bg-gray-800 my-2 p-3" > <div className="rounded-md shadow-sm shadow-pink-500 p-2"> <BiTransfer /> </div> <div> <h4 className="text-sm">{tx.title} Transfered</h4> <small className="flex flex-row justify-start items-center"> <span className="mr-1">Received by</span> <a href="#" className="text-pink-500 mr-2"> {truncate(tx.owner, 4, 4, 11)} </a> <a href="#"> <MdOpenInNew /> </a> </small> </div> <p className="text-sm font-medium">{tx.cost}ETH</p> </div> ))} </div> {collection.length > 0 && transactions.length > collection.length ? ( <div className="text-center my-5"> <button className="shadow-xl shadow-black text-white bg-[#e32970] hover:bg-[#bd255f] rounded-full cursor-pointer p-2" onClick={() => setEnd(end + count)} > Load More </button> </div> ) : null} </div> </div> ) } export default Transactions


पाद घटक


यह घटक पृष्ठ के निचले भाग में बस कुछ सुंदर लिंक प्रदर्शित करता है, जब यह कार्यात्मकता की बात आती है तो यह बहुत कुछ नहीं करता है लेकिन उपयोगकर्ता इंटरफ़ेस को पूरक करता है। इसके कोड नीचे लिखे गए हैं।


 import timelessLogo from '../assets/timeless.png' const Footer = () => ( <div className="w-full flex md:justify-center justify-between items-center flex-col p-4 gradient-bg-footer"> <div className="w-full flex sm:flex-row flex-col justify-between items-center my-4"> <div className="flex flex-[0.25] justify-center items-center"> <img src={timelessLogo} alt="logo" className="w-32" /> </div> <div className="flex flex-1 justify-evenly items-center flex-wrap sm:mt-0 mt-5 w-full"> <p className="text-white text-base text-center mx-2 cursor-pointer"> Market </p> <p className="text-white text-base text-center mx-2 cursor-pointer"> Artist </p> <p className="text-white text-base text-center mx-2 cursor-pointer"> Features </p> <p className="text-white text-base text-center mx-2 cursor-pointer"> Community </p> </div> <div className="flex flex-[0.25] justify-center items-center"> <p className="text-white text-right text-xs">&copy;2022 All rights reserved</p> </div> </div> </div> ) export default Footer


बढ़िया, यह स्पष्ट घटकों के लिए है, आइए छिपे हुए घटकों को शामिल करें जो केवल एक मोडल इंटरफ़ेस के माध्यम से लागू होते हैं।


एनएफटी घटक बनाएं


यह घटक एक छवि, शीर्षक, मूल्य और विवरण की आपूर्ति करके नए एनएफटी बनाने के कर्तव्य से जुड़ा हुआ है। Mint Now बटन पर क्लिक करने के बाद, छवि आईपीएफएस (इंटर प्लैनेटरी फाइल सिस्टम) पर अपलोड हो जाती है और एक छवि यूआरएल वापस कर दिया जाता है।


उपयोगकर्ता द्वारा अपने मेटामास्क वॉलेट के साथ लेन-देन को अधिकृत करने के तुरंत बाद, फॉर्म में दिए गए एनएफटी डेटा के साथ लौटाया गया छवि यूआरएल हमारे स्मार्ट कॉन्ट्रैक्ट को खनन के लिए भेजा जाता है।


लेन-देन के पूरा होने पर, एनएफटी को कलाकृतियों में सूचीबद्ध किया जाता है, और इच्छुक खरीदार उन्हें खरीद सकते हैं और यहां तक कि उनकी कीमतें भी बदल सकते हैं। विवरण के लिए नीचे दिया गया कोड देखें।


 import { useGlobalState, setGlobalState, setLoadingMsg, setAlert, } from '../store' import { mintNFT } from '../TimelessNFT' import { useState } from 'react' import { FaTimes } from 'react-icons/fa' import { create } from 'ipfs-http-client' const client = create('https://ipfs.infura.io:5001/api/v0') const CreateNFT = () => { const [modal] = useGlobalState('modal') const [title, setTitle] = useState('') const [price, setPrice] = useState('') const [description, setDescription] = useState('') const [fileUrl, setFileUrl] = useState('') const [imgBase64, setImgBase64] = useState(null) const onChange = async (e) => { const reader = new FileReader() if (e.target.files[0]) reader.readAsDataURL(e.target.files[0]) reader.onload = (readerEvent) => { const file = readerEvent.target.result setImgBase64(file) setFileUrl(e.target.files[0]) } } const handleSubmit = async (e) => { e.preventDefault() if (!title || !price || !description) return setGlobalState('modal', 'scale-0') setGlobalState('loading', { show: true, msg: 'Uploading IPFS data...' }) try { const created = await client.add(fileUrl) const metadataURI = `https://ipfs.infura.io/ipfs/${created.path}` const nft = { title, price, description, metadataURI } setLoadingMsg('Intializing transaction...') mintNFT(nft).then((res) => { if (res) { setFileUrl(metadataURI) resetForm() setAlert('Minting completed...', 'green') window.location.reload() } }) } catch (error) { console.log('Error uploading file: ', error) setAlert('Minting failed...', 'red') } } const closeModal = () => { setGlobalState('modal', 'scale-0') resetForm() } const resetForm = () => { setFileUrl('') setImgBase64(null) setTitle('') setPrice('') setDescription('') } return ( <div className={`fixed top-0 left-0 w-screen h-screen flex items-center justify-center bg-black bg-opacity-50 transform transition-transform duration-300 ${modal}`} > <div className="bg-[#151c25] shadow-xl shadow-[#e32970] rounded-xl w-11/12 md:w-2/5 h-7/12 p-6"> <form className="flex flex-col"> <div className="flex flex-row justify-between items-center"> <p className="font-semibold text-gray-400">Add NFT</p> <button type="button" onClick={closeModal} className="border-0 bg-transparent focus:outline-none" > <FaTimes className="text-gray-400" /> </button> </div> <div className="flex flex-row justify-center items-center rounded-xl mt-5"> <div className="shrink-0 rounded-xl overflow-hidden h-20 w-20"> <img alt="NFT" className="h-full w-full object-cover cursor-pointer" src={ imgBase64 || 'https://images.unsplash.com/photo-1580489944761-15a19d654956?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1361&q=80' } /> </div> </div> <div className="flex flex-row justify-between items-center bg-gray-800 rounded-xl mt-5"> <label className="block"> <span className="sr-only">Choose profile photo</span> <input type="file" accept="image/png, image/gif, image/jpeg, image/webp" className="block w-full text-sm text-slate-500 file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:text-sm file:font-semibold file:bg-[#19212c] file:text-gray-400 hover:file:bg-[#1d2631] cursor-pointer focus:ring-0 focus:outline-none" onChange={onChange} required /> </label> </div> <div className="flex flex-row justify-between items-center bg-gray-800 rounded-xl mt-5"> <input className="block w-full text-sm text-slate-500 bg-transparent border-0 focus:outline-none focus:ring-0" type="text" name="title" placeholder="Title" onChange={(e) => setTitle(e.target.value)} value={title} required /> </div> <div className="flex flex-row justify-between items-center bg-gray-800 rounded-xl mt-5"> <input className="block w-full text-sm text-slate-500 bg-transparent border-0 focus:outline-none focus:ring-0" type="number" step={0.01} min={0.01} name="price" placeholder="Price (Eth)" onChange={(e) => setPrice(e.target.value)} value={price} required /> </div> <div className="flex flex-row justify-between items-center bg-gray-800 rounded-xl mt-5"> <textarea className="block w-full text-sm resize-none text-slate-500 bg-transparent border-0 focus:outline-none focus:ring-0 h-20" type="text" name="description" placeholder="Description" onChange={(e) => setDescription(e.target.value)} value={description} required ></textarea> </div> <button type="submit" onClick={handleSubmit} className="flex flex-row justify-center items-center w-full text-white text-md bg-[#e32970] hover:bg-[#bd255f] py-2 px-5 rounded-full drop-shadow-xl border border-transparent hover:bg-transparent hover:text-[#e32970] hover:border hover:border-[#bd255f] focus:outline-none focus:ring mt-5" > Mint Now </button> </form> </div> </div> ) } export default CreateNFT


शोएनएफटी घटक

यह घटक एक विशिष्ट एनएफटी के बारे में अधिक जानकारी प्रदर्शित करता है, मालिक को कीमत बदलने के लिए एक बटन की पेशकश करता है, और खरीदार को एनएफटी खरीदने या विक्रेता के साथ चैट करने के लिए एक बटन प्रदान करता है। अधिक विवरण के लिए नीचे दिया गया कोड देखें।


 import Chat from './Chat' import Identicon from 'react-identicons' import { FaTimes } from 'react-icons/fa' import { buyNFT } from '../TimelessNFT' import { useGlobalState, setGlobalState, truncate, setAlert } from '../store' import { useState } from 'react' import { getMessages } from '../CometChat' const ShowNFT = () => { const [showModal] = useGlobalState('showModal') const [chatOpened] = useGlobalState('chatOpened') const [currentUser] = useGlobalState('currentUser') const [connectedAccount] = useGlobalState('connectedAccount') const [nft] = useGlobalState('nft') const [messages, setMessages] = useState([]) const onChangePrice = () => { setGlobalState('nft', nft) setGlobalState('showModal', 'scale-0') setGlobalState('updateModal', 'scale-100') } const onChatSeller = () => { if (currentUser?.uid.toLowerCase() != connectedAccount.toLowerCase()) return alert('Please login to receive chats from buyers!') getMessages(nft.owner).then((msgs) => { setMessages( msgs.filter((msg) => { return ( !!!msg?.deletedAt && !!!msg?.action && (msg?.conversationId == `${msg?.rawMessage.receiver}_user_${msg?.rawMessage.sender}` || msg?.conversationId == `${msg?.rawMessage.sender}_user_${msg?.rawMessage.receiver}`) ) }) ) setGlobalState('nft', nft) setGlobalState('chatOpened', true) }) } const handleNFTPurchase = () => { setGlobalState('showModal', 'scale-0') setGlobalState('loading', { show: true, msg: 'Initializing NFT transfer...', }) try { buyNFT(nft).then((res) => { if (res) { setAlert('Transfer completed...', 'green') window.location.reload() } }) } catch (error) { console.log('Error transfering NFT: ', error) setAlert('Purchase failed...', 'red') } } return ( <div> {chatOpened ? ( <Chat receiver={nft.owner} chats={messages} /> ) : ( <div className={`fixed top-0 left-0 w-screen h-screen flex items-center justify-center bg-black bg-opacity-50 transform transition-transform duration-300 ${showModal}`} > <div className="bg-[#151c25] shadow-xl shadow-[#e32970] rounded-xl w-11/12 md:w-2/5 h-7/12 p-6"> <div className="flex flex-col"> <div className="flex flex-row justify-between items-center"> <p className="font-semibold text-gray-400">Buy NFT</p> <button type="button" onClick={() => setGlobalState('showModal', 'scale-0')} className="border-0 bg-transparent focus:outline-none" > <FaTimes className="text-gray-400" /> </button> </div> <div className="flex flex-row justify-center items-center rounded-xl mt-5"> <div className="shrink-0 rounded-xl overflow-hidden h-40 w-40"> <img className="h-full w-full object-cover cursor-pointer" src={nft?.metadataURI} alt={nft?.title} /> </div> </div> <div className="flex flex-col justify-start rounded-xl mt-5"> <h4 className="text-white font-semibold">{nft?.title}</h4> <p className="text-gray-400 text-xs my-1">{nft?.description}</p> <div className="flex justify-between items-center mt-3 text-white"> <div className="flex justify-start items-center"> <Identicon string={nft?.owner.toLowerCase()} size={50} className="h-10 w-10 object-contain rounded-full mr-3" /> <div className="flex flex-col justify-center items-start"> <small className="text-white font-bold">@owner</small> <small className="text-pink-800 font-semibold"> {nft?.owner ? truncate(nft.owner, 4, 4, 11) : '...'} </small> </div> </div> <div className="flex flex-col"> <small className="text-xs">Current Price</small> <p className="text-sm font-semibold">{nft?.cost} ETH</p> </div> </div> </div> {connectedAccount != nft?.owner ? ( <div className="flex flex-row justify-between items-center"> <button className="flex flex-row justify-center items-center w-full text-white text-md bg-[#e32970] hover:bg-[#bd255f] py-2 px-5 rounded-full drop-shadow-xl border border-transparent hover:bg-transparent hover:text-[#e32970] hover:border hover:border-[#bd255f] focus:outline-none focus:ring mt-5" onClick={handleNFTPurchase} > Purchase Now </button> <button className="flex flex-row justify-center items-center w-full text-white text-md bg-transparent py-2 px-5 rounded-full drop-shadow-xl border border-transparent hover:bg-transparent hover:text-[#e32970] focus:outline-none focus:ring mt-5" onClick={onChatSeller} > Chat with Seller </button> </div> ) : ( <button className="flex flex-row justify-center items-center w-full text-white text-md bg-[#e32970] hover:bg-[#bd255f] py-2 px-5 rounded-full drop-shadow-xl border border-transparent hover:bg-transparent hover:text-[#e32970] hover:border hover:border-[#bd255f] focus:outline-none focus:ring mt-5" onClick={onChangePrice} > Change Price </button> )} </div> </div> </div> )} </div> ) } export default ShowNFT


UpdateNFT घटक

इस घटक को एनएफटी की कीमत बदलने का काम सौंपा गया है। यह क्रिया केवल NFT के स्वामी द्वारा ही की जा सकती है। जबकि यह विकल्प उपलब्ध है, इन परिवर्तनों को प्रभावी करने में कुछ गैस शुल्क लगेगा। एक बार जब एनएफटी दूसरे खरीदार के साथ हाथ मिलाता है, तो नया मालिक कीमत बढ़ाने का फैसला कर सकता है, और इसीलिए यह विकल्प उपलब्ध कराया गया था। नीचे दिए गए कोड स्निपेट को देखें।


 import { useGlobalState, setGlobalState, setLoadingMsg, setAlert, } from '../store' import { updateNFT } from '../TimelessNFT' import { useState } from 'react' import { FaTimes } from 'react-icons/fa' const UpdateNFT = () => { const [modal] = useGlobalState('updateModal') const [nft] = useGlobalState('nft') const [price, setPrice] = useState('') const handleSubmit = async (e) => { e.preventDefault() if (!price || price <= 0) return setGlobalState('modal', 'scale-0') setGlobalState('loading', { show: true, msg: 'Initiating price update...' }) try { setLoadingMsg('Price updating...') setGlobalState('updateModal', 'scale-0') updateNFT({...nft, cost: price}).then((res) => { if (res) { setAlert('Price updated...', 'green') window.location.reload() } }) } catch (error) { console.log('Error updating file: ', error) setAlert('Update failed...', 'red') } } return ( <div className={`fixed top-0 left-0 w-screen h-screen flex items-center justify-center bg-black bg-opacity-50 transform transition-transform duration-300 ${modal}`} > <div className="bg-[#151c25] shadow-xl shadow-[#e32970] rounded-xl w-11/12 md:w-2/5 h-7/12 p-6"> <form className="flex flex-col"> <div className="flex flex-row justify-between items-center"> <p className="font-semibold text-gray-400">{nft?.title}</p> <button type="button" onClick={() => setGlobalState('updateModal', 'scale-0')} className="border-0 bg-transparent focus:outline-none" > <FaTimes className="text-gray-400" /> </button> </div> <div className="flex flex-row justify-center items-center rounded-xl mt-5"> <div className="shrink-0 rounded-xl overflow-hidden h-20 w-20"> <img alt="NFT" className="h-full w-full object-cover cursor-pointer" src={nft?.metadataURI} /> </div> </div> <div className="flex flex-row justify-between items-center bg-gray-800 rounded-xl mt-5"> <input className="block w-full text-sm text-slate-500 bg-transparent border-0 focus:outline-none focus:ring-0" type="number" step={0.01} min={0.01} name="price" placeholder="Price (Eth)" onChange={(e) => setPrice(e.target.value)} required /> </div> <button type="submit" onClick={handleSubmit} className="flex flex-row justify-center items-center w-full text-white text-md bg-[#e32970] hover:bg-[#bd255f] py-2 px-5 rounded-full drop-shadow-xl border border-transparent hover:bg-transparent hover:text-[#e32970] hover:border hover:border-[#bd255f] focus:outline-none focus:ring mt-5" > Update Now </button> </form> </div> </div> ) } export default UpdateNFT


चैटलिस्ट घटक

इस घटक से पता चलता है कि उपयोगकर्ता ने प्लेटफ़ॉर्म पर विक्रेता या खरीदार के साथ हाल की चैट की है। घटक उनकी बातचीत में भेजे गए अंतिम संदेश को भी कैप्चर करता है। प्रत्येक वार्तालाप पर एक क्लिक चैट इंटरफ़ेस पर ले जाएगा। नीचे दिए गए कोड को देखें।


 import Chat from './Chat' import Moment from 'react-moment' import { useState } from 'react' import { FaTimes } from 'react-icons/fa' import { setGlobalState, truncate, useGlobalState } from '../store' import { getMessages } from '../CometChat' const ChatList = ({ users }) => { const [messages, setMessages] = useState([]) const [receiver, setReceiver] = useState('') const [recentChatOpened] = useGlobalState('recentChatOpened') const [connectedAccount] = useGlobalState('connectedAccount') const onEnterChat = (receiver) => { setReceiver(receiver) getMessages(receiver).then((msgs) => { setMessages( msgs.filter((msg) => { return ( !!!msg?.deletedAt && !!!msg?.action && msg?.conversationId == `${msg?.rawMessage.receiver}_user_${msg?.rawMessage.sender}` ) }) ) setGlobalState('recentChatOpened', true) }) } return ( <div> {recentChatOpened ? ( <Chat receiver={receiver} chats={messages} /> ) : ( <div className={`fixed top-0 left-0 w-screen h-screen flex items-center justify-center bg-black bg-opacity-50 transform transition-transform duration-300 scale-100`} > <div className="bg-[#151c25] shadow-xl shadow-[#e32970] rounded-xl w-11/12 md:w-2/5 h-7/12 p-6"> <div className="flex flex-col text-gray-400"> <div className="flex flex-row justify-between items-center"> <p className="font-semibold text-gray-400">Conversations</p> <button type="button" onClick={() => setGlobalState('recentOpened', false)} className="border-0 bg-transparent focus:outline-none" > <FaTimes /> </button> </div> <div className="h-[calc(100vh_-_20rem)] overflow-y-auto sm:pr-4 my-3"> {users.map((user, i) => ( <button key={i} className="flex flex-row justify-between w-full items-center bg-gray-800 hover:bg-gray-900 rounded-md px-4 py-3 my-1 cursor-pointer transform transition-transform duration-300" onClick={() => onEnterChat(user?.lastMessage.sender.uid)} > <div className="flex flex-col text-left"> <h4 className="text-sm text-[#e32970] font-semiBold"> @{truncate(user?.lastMessage.sender.uid, 4, 4, 11)} </h4> <p className="text-xs"> {user?.lastMessage.text} </p> </div> <Moment className="text-xs font-bold" unix date={user?.lastMessage.sentAt} format="YYYY/MM/D hh:mm A" /> </button> ))} </div> </div> </div> </div> )} </div> ) } export default ChatList


चैट घटक

यह घटक दो उपयोगकर्ताओं को एक-के-बाद-एक चैट में शामिल करने के लिए ज़िम्मेदार है। ऊपर दी गई छवि दो अलग-अलग ब्राउज़रों से एक खरीदार और एक विक्रेता के बीच मंच पर बातचीत दिखाती है। इसके कार्यान्वयन के लिए नीचे दिया गया कोड देखें।


 import Identicon from 'react-identicons' import { useGlobalState, setGlobalState, truncate } from '../store' import { sendMessage, CometChat } from '../CometChat' import { useEffect, useState } from 'react' import { FaTimes } from 'react-icons/fa' const Chat = ({ receiver, chats }) => { const [connectedAccount] = useGlobalState('connectedAccount') const [message, setMessage] = useState('') const [messages, setMessages] = useState(chats) const handleSubmit = async (e) => { e.preventDefault() sendMessage(receiver, message).then((msg) => { setMessages((prevState) => [...prevState, msg]) setMessage('') scrollToEnd() }) } const listenForMessage = (listenerID) => { CometChat.addMessageListener( listenerID, new CometChat.MessageListener({ onTextMessageReceived: (message) => { setMessages((prevState) => [...prevState, message]) scrollToEnd() }, }) ) } const onClose = () => { setGlobalState('chatOpened', false) setGlobalState('recentChatOpened', false) } const scrollToEnd = () => { const element = document.getElementById('messages-container') element.scrollTop = element.scrollHeight } useEffect(() => { listenForMessage(receiver) }, [receiver]) return ( <div className={`fixed top-0 left-0 w-screen h-screen flex items-center justify-center bg-black bg-opacity-50 transform transition-transform duration-300 scale-100`} > <div className="bg-[#151c25] shadow-xl shadow-[#e32970] rounded-xl w-5/6 h-5/6 p-6"> <div className="flex flex-col text-gray-400"> <div className="flex flex-row justify-between items-center"> <div className="flex flex-row justify-center items-center"> <div className="shrink-0 rounded-full overflow-hidden h-10 w-10 mr-3"> <Identicon string={receiver.toLowerCase()} size={50} className="h-full w-full object-cover cursor-pointer rounded-full" /> </div> <p className="font-bold">@{receiver ? truncate(receiver, 4, 4, 11) : '...'}</p> </div> <button type="button" onClick={onClose} className="border-0 bg-transparent focus:outline-none" > <FaTimes /> </button> </div> <div id="messages-container" className="h-[calc(100vh_-_20rem)] overflow-y-auto sm:pr-4 my-3" > {messages.map((msg, i) => msg?.receiverId?.toLowerCase() == connectedAccount.toLowerCase() ? ( <div key={i} className="flex flex-row justify-start items-center mt-5" > <div className="flex flex-col justify-start items-start"> <h4 className="text-[#e32970]"> @{receiver ? truncate(receiver, 4, 4, 11) : '...'} </h4> <p className="text-xs">{msg.text}</p> </div> </div> ) : ( <div key={i} className="flex flex-row justify-end items-center mt-5" > <div className="flex flex-col justify-start items-end"> <h4 className="text-[#e32970]">@you</h4> <p className="text-xs">{msg.text}</p> </div> </div> ) )} </div> <form onSubmit={handleSubmit} className="flex flex-row justify-between items-center bg-gray-800 rounded-xl mt-5" > <input className="block w-full text-sm resize-none text-slate-500 bg-transparent border-0 focus:outline-none focus:ring-0 h-20" type="text" name="message" placeholder="Write message..." onChange={(e) => setMessage(e.target.value)} value={message} required /> </form> </div> </div> </div> ) } export default Chat


अच्छा, अब जब हमने उन शानदार घटकों को शामिल कर लिया है, तो आइए इसे इन अंतिम दो के साथ समाप्त करें।


लोड हो रहा है घटक

लेन-देन की प्रक्रिया में होने पर यह घटक केवल वर्तमान गतिविधि और स्थिति को प्रदर्शित करता है। नीचे दिए गए कोड को देखें।


 import { useGlobalState } from '../store' const Loading = () => { const [loading] = useGlobalState('loading') return ( <div className={`fixed top-0 left-0 w-screen h-screen flex items-center justify-center bg-black bg-opacity-50 transform transition-transform duration-300 ${loading.show ? 'scale-100' : 'scale-0'}`} > <div className="flex flex-col justify-center items-center bg-[#151c25] shadow-xl shadow-[#e32970] rounded-xl min-w-min px-10 pb-2" > <div className="flex flex-row justify-center items-center"> <div className="lds-dual-ring scale-50"></div> <p className="text-lg text-white">Processing...</p> </div> <small className="text-white">{loading.msg}</small> </div> </div> ) } export default Loading


ऐप घटक यह फ़ाइल इस कार्य में चर्चा किए गए उपरोक्त घटक को बंडल करती है। यह ठीक उसी तरह है जैसे एक ReactJs आर्किटेक्चर काम करता है। नीचे दिए गए कोड देखें।


 import Alert from './components/Alert' import Artworks from './components/Artworks' import CreateNFT from './components/CreateNFT' import Footer from './components/Footer' import Header from './components/Header' import Hero from './components/Hero' import Loading from './components/Loading' import ShowNFT from './components/ShowNFT' import Transactions from './components/Transactions' import UpdateNFT from './components/UpdateNFT' import { isUserLoggedIn } from './CometChat' import { loadWeb3 } from './TimelessNFT' import { useEffect } from 'react' const App = () => { useEffect(() => { loadWeb3() isUserLoggedIn() }, []) return ( <div className="min-h-screen"> <div className="gradient-bg-hero"> <Header /> <Hero /> </div> <Artworks /> <Transactions /> <CreateNFT /> <UpdateNFT /> <ShowNFT /> <Footer /> <Alert /> <Loading /> </div> ) } export default App


बहुत बढ़िया, हमने अभी-अभी विभिन्न घटकों का एकीकरण पूरा किया है, आइए इसे इस परियोजना के अन्य भागों के साथ जोड़ दें।

अन्य आवश्यक फ़ाइलें

यह एप्लिकेशन एक राज्य प्रबंधन स्टोर, एक कॉमेटचैट एसडीके और एक अनुबंध सेवा फ़ाइल का उपयोग करता है। आइए एक के बाद एक उन पर एक नजर डालते हैं।


स्टोर यह राज्य प्रबंधन फ़ाइल react-hooks-global-state npm पैकेज का उपयोग करती है। यह Redux की तुलना में सरल, तेज और आसान है। इस ऐप में उपयोग किए जाने वाले सभी वैश्विक चर और कार्य इस स्टोर में बनाए गए थे।


प्रोजेक्ट के मूल में, src डायरेक्टरी में जाएँ और store नाम का फोल्डर बनाएँ। अब, इस स्टोर फोल्डर में index.js नाम की एक फाइल बनाएं और उसके अंदर नीचे दिए गए कोड पेस्ट करें।


 import { createGlobalState } from 'react-hooks-global-state' const { setGlobalState, useGlobalState, getGlobalState } = createGlobalState({ modal: 'scale-0', updateModal: 'scale-0', mintModal: '', alert: { show: false, msg: '', color: '' }, loading: { show: false, msg: '' }, showModal: 'scale-0', chatOpened: false, recentChatOpened: false, recentOpened: false, chatList: 'scale-0', connectedAccount: '', currentUser: null, nft: null, nfts: [], transactions: [], contract: null, }) const setAlert = (msg, color = 'green') => { setGlobalState('loading', false) setGlobalState('alert', { show: true, msg, color }) setTimeout(() => { setGlobalState('alert', { show: false, msg: '', color }) }, 6000) } const setLoadingMsg = (msg) => { const loading = getGlobalState('loading') setGlobalState('loading', { ...loading, msg }) } const truncate = (text, startChars, endChars, maxLength) => { if (text.length > maxLength) { var start = text.substring(0, startChars) var end = text.substring(text.length - endChars, text.length) while (start.length + end.length < maxLength) { start = start + '.' } return start + end } return text } export { useGlobalState, setGlobalState, getGlobalState, setAlert, setLoadingMsg, truncate, }


कॉमेटचैट सेवा इस फाइल में कॉमेटचैट एसडीके के साथ संचार करने के लिए सभी आवश्यक कार्य हैं। नीचे दिए गए कोड देखें।


 import { CometChat } from '@cometchat-pro/chat' import { setGlobalState } from './store' const CONSTANTS = { APP_ID: process.env.REACT_APP_COMET_CHAT_APP_ID, REGION: process.env.REACT_APP_COMET_CHAT_REGION, Auth_Key: process.env.REACT_APP_COMET_CHAT_AUTH_KEY, } const initCometChat = async () => { const appID = CONSTANTS.APP_ID const region = CONSTANTS.REGION const appSetting = new CometChat.AppSettingsBuilder() .subscribePresenceForAllUsers() .setRegion(region) .build() await CometChat.init(appID, appSetting) .then(() => console.log('Initialization completed successfully')) .catch((error) => error) } const loginWithCometChat = async (UID) => { const authKey = CONSTANTS.Auth_Key await CometChat.login(UID, authKey) .then((user) => setGlobalState('currentUser', user)) .catch((error) => { alert(error.message) console.log(error) }) return true } const signUpWithCometChat = async (UID, name) => { let authKey = CONSTANTS.Auth_Key const user = new CometChat.User(UID) user.setName(name) await CometChat.createUser(user, authKey) .then((user) => { alert('Signed up successfully, click login now!') console.log('Logged In: ', user) }) .catch((error) => { alert(error.message) console.log(error) }) return true } const logOutWithCometChat = async () => { return await CometChat.logout() .then(() => console.log('Logged Out Successfully')) .catch((error) => error) } const isUserLoggedIn = async () => { await CometChat.getLoggedinUser() .then((user) => setGlobalState('currentUser', user)) .catch((error) => console.log('error:', error)) } const getMessages = async (UID) => { const limit = 30 const messagesRequest = new CometChat.MessagesRequestBuilder() .setUID(UID) .setLimit(limit) .build() return await messagesRequest .fetchPrevious() .then((messages) => messages) .catch((error) => error) } const sendMessage = async (receiverID, messageText) => { const receiverType = CometChat.RECEIVER_TYPE.USER const textMessage = new CometChat.TextMessage( receiverID, messageText, receiverType ) return await CometChat.sendMessage(textMessage) .then((message) => message) .catch((error) => error) } const getConversations = async () => { const limit = 30 const conversationsRequest = new CometChat.ConversationsRequestBuilder() .setLimit(limit) .build() return await conversationsRequest .fetchNext() .then((conversationList) => conversationList) } export { initCometChat, loginWithCometChat, signUpWithCometChat, logOutWithCometChat, getMessages, sendMessage, getConversations, isUserLoggedIn, CometChat, }


अनुबंध सेवा फ़ाइल इस फ़ाइल में Web3 पुस्तकालय का उपयोग करके ब्लॉकचेन पर स्मार्ट अनुबंध के साथ बातचीत करने के लिए जिम्मेदार सभी कार्य और प्रक्रियाएं शामिल हैं। नीचे दिए गए कोड देखें।


 import Web3 from 'web3' import { setGlobalState, getGlobalState, setAlert } from './store' import TimelessNFT from './abis/TimelessNFT.json' const { ethereum } = window const connectWallet = async () => { try { if (!ethereum) return alert('Please install Metamask') const accounts = await ethereum.request({ method: 'eth_requestAccounts' }) setGlobalState('connectedAccount', accounts[0]) } catch (error) { setAlert(JSON.stringify(error), 'red') } } const structuredNfts = (nfts) => { return nfts .map((nft) => ({ id: Number(nft.id), owner: nft.owner, cost: window.web3.utils.fromWei(nft.cost), title: nft.title, description: nft.description, metadataURI: nft.metadataURI, timestamp: nft.timestamp, })) .reverse() } const loadWeb3 = async () => { try { if (!ethereum) return alert('Please install Metamask') window.web3 = new Web3(ethereum) window.web3 = new Web3(window.web3.currentProvider) const web3 = window.web3 const accounts = await web3.eth.getAccounts() setGlobalState('connectedAccount', accounts[0]) const networkId = await web3.eth.net.getId() const networkData = TimelessNFT.networks[networkId] if (networkData) { const contract = new web3.eth.Contract( TimelessNFT.abi, networkData.address ) const nfts = await contract.methods.getAllNFTs().call() const transactions = await contract.methods.getAllTransactions().call() setGlobalState('nfts', structuredNfts(nfts)) setGlobalState('transactions', structuredNfts(transactions)) setGlobalState('contract', contract) } else { window.alert('TimelessNFT contract not deployed to detected network.') } } catch (error) { alert('Please connect your metamask wallet!') } } const mintNFT = async ({ title, description, metadataURI, price }) => { try { price = window.web3.utils.toWei(price.toString(), 'ether') const contract = getGlobalState('contract') const account = getGlobalState('connectedAccount') const mintPrice = window.web3.utils.toWei('0.01', 'ether') await contract.methods .payToMint(title, description, metadataURI, price) .send({ from: account, value: mintPrice }) return true } catch (error) { setAlert(error.message, 'red') } } const buyNFT = async ({ id, cost }) => { try { cost = window.web3.utils.toWei(cost.toString(), 'ether') const contract = getGlobalState('contract') const buyer = getGlobalState('connectedAccount') await contract.methods.payToBuy(Number(id)).send({ from: buyer, value: cost }) return true } catch (error) { setAlert(error.message, 'red') } } const updateNFT = async ({ id, cost }) => { try { cost = window.web3.utils.toWei(cost.toString(), 'ether') const contract = getGlobalState('contract') const buyer = getGlobalState('connectedAccount') await contract.methods.changePrice(Number(id), cost).send({ from: buyer }) return true } catch (error) { setAlert(error.message, 'red') } } export { loadWeb3, connectWallet, mintNFT, buyNFT, updateNFT }


प्रोजेक्ट एसेट इस लोगो को डाउनलोड करें और इसे अपनी रूट डायरेक्टरी में एसेट फोल्डर के अंदर शामिल करें। और इसके साथ ही, आपने इस एप्लिकेशन को चलाने के लिए आवश्यक सभी चीजों को सफलतापूर्वक शामिल कर लिया है।

सर्वर शुरू करना

इस चरण के साथ आगे बढ़ने के लिए, स्मार्ट अनुबंध को वेब पर माइग्रेट करें ताकि आप इसके साथ सहभागिता कर सकें। अपने टर्मिनल पर निम्न कोड चलाएँ।


 truffle migrate --network rinkeby


उपरोक्त कोड आपके स्मार्ट अनुबंध को Infura RPC का उपयोग करके सर्वर पर भेज देगा।


आप इस ट्यूटोरियल की शुरुआत में हमारे द्वारा स्थापित गनाचे-क्ली सर्वर का उपयोग करके एक स्थानीय ब्लॉकचेन भी स्थापित कर सकते हैं। यदि आप इस तरह से पसंद करते हैं तो इसे अपने स्थानीय ब्लॉकचेन सर्वर पर भेजने के लिए बस नीचे दिए गए कोड को चलाएं।


एक टर्मिनल रन **ganache-cli -d** खोलें और दूसरे टर्मिनल पर **truffle migrate** या **truffle deploy** करें** चलाएं।


ध्यान दें, यदि आप अपने ईवीएम के रूप में ganache-cli -क्ली का उपयोग कर रहे हैं, तो आपको मेटामास्क में लोकलहोस्ट सर्वर को भी जोड़ना होगा, और गनाचे द्वारा उत्पन्न निजी कुंजी को आयात करना होगा। मार्गदर्शन के लिए विकास पर्यावरण शुरू करना देखें


अगर आपको अपने प्रोजेक्ट के मुद्दों को हल करने में मेरी मदद चाहिए, तो इस पेज पर मुझसे सलाह लें

अब, अपने रिएक्ट एप्लिकेशन को बूट करने के लिए yarn start चलाएं। और वहां आपके पास यह एनएफटी मार्केटप्लेस पर इस बिल्ड के साथ है।


Youtube पर अभी मेरे मुफ़्त web3 ट्यूटोरियल देखें .

निष्कर्ष

हम इस एनएफटी बिल्ड की अंतिम पंक्ति में आ गए हैं, मुझे पता है कि आपने मेरे साथ एक टन मूल्य निर्माण प्राप्त किया है।


आप जो भी स्तर के हों, यदि आप अपने वेब3 विकास कौशल में तेजी से विकास करना चाहते हैं, तो मेरी निजी कक्षा में शामिल हों।


अगली बार तक इसे कुचलते रहें!


लेखक के बारे में

गॉस्पेल डार्लिंगटन एक पूर्ण-स्टैक ब्लॉकचैन डेवलपर है जिसके पास सॉफ्टवेयर विकास उद्योग में 6+ वर्षों का अनुभव है।


सॉफ्टवेयर विकास, लेखन और शिक्षण के संयोजन से, वह प्रदर्शित करता है कि ईवीएम-संगत ब्लॉकचेन नेटवर्क पर विकेंद्रीकृत अनुप्रयोगों का निर्माण कैसे किया जाता है।


उनके ढेर में JavaScript , React , Vue , Angular , Node , React Native , Solidity , NextJs और बहुत कुछ शामिल हैं।


उनके बारे में अधिक जानकारी के लिए, कृपया ट्विटर , गिटहब , लिंक्डइन , या उनकी वेबसाइट पर उनके पेज पर जाएं और उनका अनुसरण करें।